#include <string.h>
#include <stdlib.h>
#include "esp_log.h"
#include "esp_http_client.h"
#include "cJSON.h"

#include "httpClient.h"
#include "../memPool/memPool.h"

#define MAX_QUEUE_LENGTH 20
#define REALTIMEWEATHERUSERDATA         "realTimeWeather"
#define LIFEUSERDATA                    "LivIndex"
#define DAILYUSERDATA                   "DailyWeather"
#define BiliUSERDATA                    "BiliBiliInf"
#define     TAG     "http:"

static QueueHandle_t http_data_queue;
const char* RealTimeUserData = REALTIMEWEATHERUSERDATA; 
const char* LifeUserData = LIFEUSERDATA; 
const char* DailyUserData = DAILYUSERDATA; 
const char* BiliUserData = BiliUSERDATA;


static bool parse_Weather_json(const char *json_str, weather_now_t *weather);
static void printWeatherData(weather_now_t *weather);
static bool parse_Life_json(const char *json_str, weather_data_t *weather_data);
static void printLifeData(weather_data_t* weatherData);
static bool parse_Daily_json(const char *json_str, weather_forecast_t *forecast);
static void printDailyData(weather_forecast_t* weatherData);
static bool parse_Bili_json(const char *json_str, user_relation_response_t *response);
static void printBiliData(user_relation_response_t* user_relation_response);

// HTTP事件处理程序
static esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    static uint8_t *output_buffer;
    static int output_len;
    static size_t buffer_size = 0;
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                // if (evt->user_data) {
                //     memcpy(evt->user_data + output_len, evt->data, evt->data_len);
                // } else {
                    if (output_buffer == NULL) {
                        output_buffer = allocate_from_pool(evt->data_len + 1024, &buffer_size);
                        if (output_buffer == NULL) {
                            ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
                            return ESP_FAIL;
                        }
                        output_len = 0;
                    }
                    if (output_len + evt->data_len > buffer_size) {
                        ESP_LOGW(TAG, "Data exceeds initial allocation, need to handle");
                        // 这里可以实现动态扩容或使用多个内存块
                        return ESP_FAIL;
                    }
                     memcpy(output_buffer + output_len, evt->data, evt->data_len);
                // }
                output_len += evt->data_len;
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
            if (output_buffer != NULL) {

                http_message_t msg = {
                    .data = output_buffer,
                    .length = output_len,
                    .status = esp_http_client_get_status_code(evt->client),
                    .user_ctx = evt->user_data
                };
                if (xQueueSend(http_data_queue, &msg, pdMS_TO_TICKS(100)) != pdTRUE) {
                    ESP_LOGE(TAG, "Queue full, dropping message");
                    free_to_pool(output_buffer);
                }
                // ESP_LOGI("WRATHER JSON", "%s",output_buffer);
                // free_to_pool(output_buffer);
            }
            output_len = 0;
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
            if (output_buffer != NULL) {
                free_to_pool(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
        default:
            break;
    }
    return ESP_OK;
}

// 获取天气信息的任务
void get_weather_task(void *pvParameters)
{
    esp_http_client_handle_t client;
    ESP_LOGI(TAG, "Starting weather task");
    init_memory_pool();
    http_data_queue = xQueueCreate(MAX_QUEUE_LENGTH, sizeof(http_message_t));

    char urlRealTime[256],urlLife[256],urlDaily[256],urlBili[256];
    snprintf(urlRealTime, sizeof(urlRealTime), "https://api.seniverse.com/v3/weather/now.json?key=SEYjnR2_UPpQBVCGX&location=nanjing&language=zh-Hans&unit=c");
    snprintf(urlLife, sizeof(urlLife), "https://api.seniverse.com/v3/life/suggestion.json?key=SEYjnR2_UPpQBVCGX&location=nanjing&language=zh-Hans&unit=c");
    snprintf(urlDaily, sizeof(urlDaily), "https://api.seniverse.com/v3/weather/daily.json?key=SEYjnR2_UPpQBVCGX&location=nanjing&language=zh-Hans&unit=c");
    snprintf(urlBili, sizeof(urlBili), "https://api.bilibili.com/x/relation/stat?vmid=1668969737&jsonp=jsonp");

    esp_http_client_config_t configRealTime = {
        .url = urlRealTime,
        .event_handler = _http_event_handler,
        .cert_pem = NULL, // 不提供证书
        .skip_cert_common_name_check = true,
        // .user_data = NULL, // 可以传递缓冲区指针
        .user_data = RealTimeUserData, // 可以传递缓冲区指针
    };
    esp_http_client_config_t configLife = {
        .url = urlLife,
        .event_handler = _http_event_handler,
        .cert_pem = NULL, // 不提供证书
        .skip_cert_common_name_check = true,
        // .user_data = NULL, // 可以传递缓冲区指针
        .user_data = LifeUserData, // 可以传递缓冲区指针
    };
    esp_http_client_config_t configDaily = {
        .url = urlDaily,
        .event_handler = _http_event_handler,
        .cert_pem = NULL, // 不提供证书
        .skip_cert_common_name_check = true,
        // .user_data = NULL, // 可以传递缓冲区指针
        .user_data = DailyUserData, // 可以传递缓冲区指针
    };
    esp_http_client_config_t configBili = {
        .url = urlBili,
        .event_handler = _http_event_handler,
        .cert_pem = NULL, // 不提供证书
        .skip_cert_common_name_check = true,
        // .user_data = NULL, // 可以传递缓冲区指针
        .user_data = BiliUserData, // 可以传递缓冲区指针
    };
    while(1)
    {
        client = esp_http_client_init(&configRealTime);
        esp_http_client_perform(client);
        esp_http_client_cleanup(client);
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 每10秒获取一次天气

        client = esp_http_client_init(&configLife);
        esp_http_client_perform(client);
        esp_http_client_cleanup(client);
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 每10秒获取一次天气

        client = esp_http_client_init(&configDaily);
        esp_http_client_perform(client);
        esp_http_client_cleanup(client);
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 每10秒获取一次天气

        client = esp_http_client_init(&configBili);
        esp_http_client_perform(client);
        esp_http_client_cleanup(client);
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 每10秒获取一次天气
    }
}

void rec_analyze_http_data_task(void *pvParameters)
{
    http_message_t msg;
    weather_data_t weather_data;
    weather_forecast_t weather_forecast;
    user_relation_response_t user_relation_response;
    weather_now_t weather_now;
    while(1)
    {
        if (xQueueReceive(http_data_queue, &msg, portMAX_DELAY)) {
            if(strncmp((char*)msg.user_ctx, REALTIMEWEATHERUSERDATA, strlen(REALTIMEWEATHERUSERDATA)) == 0)
            {
                if(parse_Weather_json((char*)msg.data, &weather_now))
                {
                    // printWeatherData(&weather_now);
                }
                else
                {
                    ESP_LOGE(TAG, "json analyze err");
                }
            }
            else if(strncmp((char*)msg.user_ctx, LIFEUSERDATA, strlen(LIFEUSERDATA)) == 0)
            {
                if(parse_Life_json((char*)msg.data, &weather_data))
                {
                    // printLifeData(&weather_data);
                }
                else
                {
                    ESP_LOGE(TAG, "json analyze err");
                }
            }
            else if(strncmp((char*)msg.user_ctx, DAILYUSERDATA, strlen(DAILYUSERDATA)) == 0)
            {
                if(parse_Daily_json((char*)msg.data, &weather_forecast))
                {
                    // printDailyData(&weather_forecast);
                }
                else
                {
                    ESP_LOGE(TAG, "json analyze err");
                }

            }
            else if(strncmp((char*)msg.user_ctx, BiliUSERDATA, strlen(BiliUSERDATA)) == 0)
            {
                if(parse_Bili_json((char*)msg.data, &user_relation_response) )
                {
                    // printBiliData(&user_relation_response);
                }
                else
                {
                    ESP_LOGE(TAG, "json analyze err");
                }
            }
            else
            {
                ESP_LOGE(TAG, "no msg type");
            }
            free_to_pool(msg.data);
            
            // 性能监控
            // static uint32_t processed_count = 0;
            // processed_count++;
            // if (processed_count % 100 == 0) {
            //     ESP_LOGI(TAG, "Processed %d HTTP messages", processed_count);
                
            //     // 监控队列状态
            //     UBaseType_t messages_waiting = uxQueueMessagesWaiting(http_data_queue);
            //     if (messages_waiting > MAX_QUEUE_LENGTH / 2) {
            //         ESP_LOGW(TAG, "Queue backlog: %ld messages", (uint32_t)messages_waiting);
            //     }
            // }
        }
    }
}

static bool parse_Weather_json(const char *json_str, weather_now_t *weather) 
{
    if (json_str == NULL || weather == NULL) {
        ESP_LOGE(TAG, "Invalid parameters");
        return false;
    }

    // 初始化结构体
    memset(weather, 0, sizeof(weather_now_t));
    
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            ESP_LOGE(TAG, "JSON parse error before: %s", error_ptr);
        }
        return false;
    }

    // 获取results数组
    cJSON *results = cJSON_GetObjectItemCaseSensitive(root, "results");
    if (!cJSON_IsArray(results) || cJSON_GetArraySize(results) == 0) {
        ESP_LOGE(TAG, "No results found or results is not an array");
        cJSON_Delete(root);
        return false;
    }

    // 获取第一个结果
    cJSON *first_result = cJSON_GetArrayItem(results, 0);
    if (first_result == NULL) {
        ESP_LOGE(TAG, "Failed to get first result");
        cJSON_Delete(root);
        return false;
    }

    // 解析location信息
    cJSON *location = cJSON_GetObjectItemCaseSensitive(first_result, "location");
    if (cJSON_IsObject(location)) {
        cJSON *id = cJSON_GetObjectItemCaseSensitive(location, "id");
        cJSON *name = cJSON_GetObjectItemCaseSensitive(location, "name");
        cJSON *country = cJSON_GetObjectItemCaseSensitive(location, "country");
        cJSON *path = cJSON_GetObjectItemCaseSensitive(location, "path");
        cJSON *timezone = cJSON_GetObjectItemCaseSensitive(location, "timezone");
        cJSON *timezone_offset = cJSON_GetObjectItemCaseSensitive(location, "timezone_offset");

        if (cJSON_IsString(id)) 
            strncpy(weather->location.location_id, id->valuestring, sizeof(weather->location.location_id));
        if (cJSON_IsString(name)) 
            strncpy(weather->location.location_name, name->valuestring, sizeof(weather->location.location_name));
        if (cJSON_IsString(country)) 
            strncpy(weather->location.country, country->valuestring, sizeof(weather->location.country));
        if (cJSON_IsString(path)) 
            strncpy(weather->location.path, path->valuestring, sizeof(weather->location.path));
        if (cJSON_IsString(timezone)) 
            strncpy(weather->location.timezone, timezone->valuestring, sizeof(weather->location.timezone));
        if (cJSON_IsString(timezone_offset)) 
            strncpy(weather->location.timezone_offset, timezone_offset->valuestring, sizeof(weather->location.timezone_offset));
    }

    // 解析当前天气状况
    cJSON *now = cJSON_GetObjectItemCaseSensitive(first_result, "now");
    if (cJSON_IsObject(now)) {
        cJSON *text = cJSON_GetObjectItemCaseSensitive(now, "text");
        cJSON *code = cJSON_GetObjectItemCaseSensitive(now, "code");
        cJSON *temperature = cJSON_GetObjectItemCaseSensitive(now, "temperature");

        if (cJSON_IsString(text)) 
            strncpy(weather->now.text, text->valuestring, sizeof(weather->now.text));
        if (cJSON_IsString(code)) 
            weather->now.code = atoi(code->valuestring);
        if (cJSON_IsString(temperature)) 
            weather->now.temperature = atoi(temperature->valuestring);
    }

    // 解析最后更新时间
    cJSON *last_update = cJSON_GetObjectItemCaseSensitive(first_result, "last_update");
    if (cJSON_IsString(last_update)) {
        strncpy(weather->last_update, last_update->valuestring, sizeof(weather->last_update));
    }

    cJSON_Delete(root);
    return true;
}

static void printWeatherData(weather_now_t *weather)
{
    char* thisTag = "current weather";
    ESP_LOGI(thisTag, "country is:%s", weather->location.country);
    ESP_LOGI(thisTag, "location_id is:%s", weather->location.location_id);
    ESP_LOGI(thisTag, "location_name is:%s", weather->location.location_name);
    ESP_LOGI(thisTag, "path is:%s", weather->location.path);
    ESP_LOGI(thisTag, "timezone is:%s", weather->location.timezone);
    ESP_LOGI(thisTag, "timezone_offset is:%s", weather->location.timezone_offset);

    ESP_LOGI(thisTag, "code is:%d", weather->now.code);
    ESP_LOGI(thisTag, "temperature is:%d", weather->now.temperature);
    ESP_LOGI(thisTag, "text is:%s", weather->now.text);

    ESP_LOGI(thisTag, "last_update is:%s", weather->last_update);
}

static bool parse_Life_json(const char *json_str, weather_data_t *weather_data) 
{
    if (json_str == NULL || weather_data == NULL) {
        ESP_LOGE(TAG, "Invalid parameters");
        return false;
    }

    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            ESP_LOGE(TAG, "JSON parse error before: %s", error_ptr);
        }
        return false;
    }

    // 获取results数组
    cJSON *results = cJSON_GetObjectItemCaseSensitive(root, "results");
    if (!cJSON_IsArray(results) || cJSON_GetArraySize(results) == 0) {
        ESP_LOGE(TAG, "No results found or results is not an array");
        cJSON_Delete(root);
        return false;
    }

    // 获取第一个结果（通常只有一个）
    cJSON *first_result = cJSON_GetArrayItem(results, 0);
    if (first_result == NULL) {
        ESP_LOGE(TAG, "Failed to get first result");
        cJSON_Delete(root);
        return false;
    }

    // 解析location信息
    cJSON *location = cJSON_GetObjectItemCaseSensitive(first_result, "location");
    if (cJSON_IsObject(location)) {
        cJSON *id = cJSON_GetObjectItemCaseSensitive(location, "id");
        cJSON *name = cJSON_GetObjectItemCaseSensitive(location, "name");
        cJSON *country = cJSON_GetObjectItemCaseSensitive(location, "country");
        cJSON *path = cJSON_GetObjectItemCaseSensitive(location, "path");
        cJSON *timezone = cJSON_GetObjectItemCaseSensitive(location, "timezone");
        cJSON *timezone_offset = cJSON_GetObjectItemCaseSensitive(location, "timezone_offset");

        if (cJSON_IsString(id)) strncpy(weather_data->location.location_id, id->valuestring, sizeof(weather_data->location.location_id));
        if (cJSON_IsString(name)) strncpy(weather_data->location.location_name, name->valuestring, sizeof(weather_data->location.location_name));
        if (cJSON_IsString(country)) strncpy(weather_data->location.country, country->valuestring, sizeof(weather_data->location.country));
        if (cJSON_IsString(path)) strncpy(weather_data->location.path, path->valuestring, sizeof(weather_data->location.path));
        if (cJSON_IsString(timezone)) strncpy(weather_data->location.timezone, timezone->valuestring, sizeof(weather_data->location.timezone));
        if (cJSON_IsString(timezone_offset)) strncpy(weather_data->location.timezone_offset, timezone_offset->valuestring, sizeof(weather_data->location.timezone_offset));
    }

    // 解析suggestion信息
    cJSON *suggestion = cJSON_GetObjectItemCaseSensitive(first_result, "suggestion");
    if (cJSON_IsObject(suggestion)) {
        // 解析洗车指数
        cJSON *car_washing = cJSON_GetObjectItemCaseSensitive(suggestion, "car_washing");
        if (cJSON_IsObject(car_washing)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(car_washing, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.car_washing_brief, brief->valuestring, sizeof(weather_data->suggestion.car_washing_brief));
        }

        // 解析穿衣指数
        cJSON *dressing = cJSON_GetObjectItemCaseSensitive(suggestion, "dressing");
        if (cJSON_IsObject(dressing)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(dressing, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.dressing_brief, brief->valuestring, sizeof(weather_data->suggestion.dressing_brief));
        }

        // 解析感冒指数
        cJSON *flu = cJSON_GetObjectItemCaseSensitive(suggestion, "flu");
        if (cJSON_IsObject(flu)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(flu, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.flu_brief, brief->valuestring, sizeof(weather_data->suggestion.flu_brief));
        }

        // 解析运动指数
        cJSON *sport = cJSON_GetObjectItemCaseSensitive(suggestion, "sport");
        if (cJSON_IsObject(sport)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(sport, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.sport_brief, brief->valuestring, sizeof(weather_data->suggestion.sport_brief));
        }

        // 解析旅游指数
        cJSON *travel = cJSON_GetObjectItemCaseSensitive(suggestion, "travel");
        if (cJSON_IsObject(travel)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(travel, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.travel_brief, brief->valuestring, sizeof(weather_data->suggestion.travel_brief));
        }

        // 解析紫外线指数
        cJSON *uv = cJSON_GetObjectItemCaseSensitive(suggestion, "uv");
        if (cJSON_IsObject(uv)) {
            cJSON *brief = cJSON_GetObjectItemCaseSensitive(uv, "brief");
            if (cJSON_IsString(brief)) strncpy(weather_data->suggestion.uv_brief, brief->valuestring, sizeof(weather_data->suggestion.uv_brief));
        }
    }

    // 解析最后更新时间
    cJSON *last_update = cJSON_GetObjectItemCaseSensitive(first_result, "last_update");
    if (cJSON_IsString(last_update)) {
        strncpy(weather_data->last_update, last_update->valuestring, sizeof(weather_data->last_update));
    }

    cJSON_Delete(root);
    return true;
}

static void printLifeData(weather_data_t* weatherData)
{
    char* thisTag = "LivIndex:";
    ESP_LOGI(thisTag, "country is:%s", weatherData->location.country);
    ESP_LOGI(thisTag, "location_id is:%s", weatherData->location.location_id);
    ESP_LOGI(thisTag, "location_name is:%s", weatherData->location.location_name);
    ESP_LOGI(thisTag, "path is:%s", weatherData->location.path);
    ESP_LOGI(thisTag, "timezone is:%s", weatherData->location.timezone);
    ESP_LOGI(thisTag, "timezone_offset is:%s", weatherData->location.timezone_offset);

    ESP_LOGI(thisTag, "car_washing_brief is:%s", weatherData->suggestion.car_washing_brief);
    ESP_LOGI(thisTag, "dressing_brief is:%s", weatherData->suggestion.dressing_brief);
    ESP_LOGI(thisTag, "flu_brief is:%s", weatherData->suggestion.flu_brief);
    ESP_LOGI(thisTag, "sport_brief is:%s", weatherData->suggestion.sport_brief);
    ESP_LOGI(thisTag, "travel_brief is:%s", weatherData->suggestion.travel_brief);
    ESP_LOGI(thisTag, "uv_brief is:%s", weatherData->suggestion.uv_brief);

    ESP_LOGI(thisTag, "last_update is:%s", weatherData->last_update);
}

static bool parse_Daily_json(const char *json_str, weather_forecast_t *forecast) 
{
    if (json_str == NULL || forecast == NULL) {
        ESP_LOGE(TAG, "Invalid parameters");
        return false;
    }

    // 初始化结构体
    memset(forecast, 0, sizeof(weather_forecast_t));
    
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            ESP_LOGE(TAG, "JSON parse error before: %s", error_ptr);
        }
        return false;
    }

    // 获取results数组
    cJSON *results = cJSON_GetObjectItemCaseSensitive(root, "results");
    if (!cJSON_IsArray(results) || cJSON_GetArraySize(results) == 0) {
        ESP_LOGE(TAG, "No results found or results is not an array");
        cJSON_Delete(root);
        return false;
    }

    // 获取第一个结果
    cJSON *first_result = cJSON_GetArrayItem(results, 0);
    if (first_result == NULL) {
        ESP_LOGE(TAG, "Failed to get first result");
        cJSON_Delete(root);
        return false;
    }

    // 解析location信息
    cJSON *location = cJSON_GetObjectItemCaseSensitive(first_result, "location");
    if (cJSON_IsObject(location)) {
        cJSON *id = cJSON_GetObjectItemCaseSensitive(location, "id");
        cJSON *name = cJSON_GetObjectItemCaseSensitive(location, "name");
        cJSON *country = cJSON_GetObjectItemCaseSensitive(location, "country");
        cJSON *path = cJSON_GetObjectItemCaseSensitive(location, "path");
        cJSON *timezone = cJSON_GetObjectItemCaseSensitive(location, "timezone");
        cJSON *timezone_offset = cJSON_GetObjectItemCaseSensitive(location, "timezone_offset");

        if (cJSON_IsString(id)) strncpy(forecast->location.location_id, id->valuestring, sizeof(forecast->location.location_id));
        if (cJSON_IsString(name)) strncpy(forecast->location.location_name, name->valuestring, sizeof(forecast->location.location_name));
        if (cJSON_IsString(country)) strncpy(forecast->location.country, country->valuestring, sizeof(forecast->location.country));
        if (cJSON_IsString(path)) strncpy(forecast->location.path, path->valuestring, sizeof(forecast->location.path));
        if (cJSON_IsString(timezone)) strncpy(forecast->location.timezone, timezone->valuestring, sizeof(forecast->location.timezone));
        if (cJSON_IsString(timezone_offset)) strncpy(forecast->location.timezone_offset, timezone_offset->valuestring, sizeof(forecast->location.timezone_offset));
    }

    // 解析daily数组（多日天气预报）
    cJSON *daily_array = cJSON_GetObjectItemCaseSensitive(first_result, "daily");
    if (cJSON_IsArray(daily_array)) {
        int array_size = cJSON_GetArraySize(daily_array);
        forecast->daily_count = (array_size > 3) ? 3 : array_size; // 最多保存7天

        for (int i = 0; i < forecast->daily_count; i++) {
            cJSON *daily_item = cJSON_GetArrayItem(daily_array, i);
            if (daily_item == NULL) continue;

            // 解析每日天气数据
            cJSON *date = cJSON_GetObjectItemCaseSensitive(daily_item, "date");
            cJSON *text_day = cJSON_GetObjectItemCaseSensitive(daily_item, "text_day");
            cJSON *code_day = cJSON_GetObjectItemCaseSensitive(daily_item, "code_day");
            cJSON *text_night = cJSON_GetObjectItemCaseSensitive(daily_item, "text_night");
            cJSON *code_night = cJSON_GetObjectItemCaseSensitive(daily_item, "code_night");
            cJSON *high = cJSON_GetObjectItemCaseSensitive(daily_item, "high");
            cJSON *low = cJSON_GetObjectItemCaseSensitive(daily_item, "low");
            cJSON *rainfall = cJSON_GetObjectItemCaseSensitive(daily_item, "rainfall");
            cJSON *precip = cJSON_GetObjectItemCaseSensitive(daily_item, "precip");
            cJSON *wind_direction = cJSON_GetObjectItemCaseSensitive(daily_item, "wind_direction");
            cJSON *wind_direction_degree = cJSON_GetObjectItemCaseSensitive(daily_item, "wind_direction_degree");
            cJSON *wind_speed = cJSON_GetObjectItemCaseSensitive(daily_item, "wind_speed");
            cJSON *wind_scale = cJSON_GetObjectItemCaseSensitive(daily_item, "wind_scale");
            cJSON *humidity = cJSON_GetObjectItemCaseSensitive(daily_item, "humidity");

            // 填充每日天气数据
            if (cJSON_IsString(date)) strncpy(forecast->daily[i].date, date->valuestring, sizeof(forecast->daily[i].date));
            if (cJSON_IsString(text_day)) strncpy(forecast->daily[i].text_day, text_day->valuestring, sizeof(forecast->daily[i].text_day));
            if (cJSON_IsString(code_day)) forecast->daily[i].code_day = atoi(code_day->valuestring);
            if (cJSON_IsString(text_night)) strncpy(forecast->daily[i].text_night, text_night->valuestring, sizeof(forecast->daily[i].text_night));
            if (cJSON_IsString(code_night)) forecast->daily[i].code_night = atoi(code_night->valuestring);
            if (cJSON_IsString(high)) forecast->daily[i].high = atoi(high->valuestring);
            if (cJSON_IsString(low)) forecast->daily[i].low = atoi(low->valuestring);
            if (cJSON_IsString(rainfall)) forecast->daily[i].rainfall = atof(rainfall->valuestring);
            if (cJSON_IsString(precip)) forecast->daily[i].precip = atof(precip->valuestring);
            if (cJSON_IsString(wind_direction)) strncpy(forecast->daily[i].wind_direction, wind_direction->valuestring, sizeof(forecast->daily[i].wind_direction));
            if (cJSON_IsString(wind_direction_degree)) forecast->daily[i].wind_direction_degree = atoi(wind_direction_degree->valuestring);
            if (cJSON_IsString(wind_speed)) forecast->daily[i].wind_speed = atof(wind_speed->valuestring);
            if (cJSON_IsString(wind_scale)) forecast->daily[i].wind_scale = atoi(wind_scale->valuestring);
            if (cJSON_IsString(humidity)) forecast->daily[i].humidity = atoi(humidity->valuestring);
        }
    }

    // 解析最后更新时间
    cJSON *last_update = cJSON_GetObjectItemCaseSensitive(first_result, "last_update");
    if (cJSON_IsString(last_update)) {
        strncpy(forecast->last_update, last_update->valuestring, sizeof(forecast->last_update));
    }

    cJSON_Delete(root);
    return true;
}

static void printDailyData(weather_forecast_t* weather_forecast)
{
    char* thisTag = "Three Day Weather:";
    ESP_LOGI(thisTag, "country is:%s", weather_forecast->location.country);
    ESP_LOGI(thisTag, "location_id is:%s", weather_forecast->location.location_id);
    ESP_LOGI(thisTag, "location_name is:%s", weather_forecast->location.location_name);
    ESP_LOGI(thisTag, "path is:%s", weather_forecast->location.path);
    ESP_LOGI(thisTag, "timezone is:%s", weather_forecast->location.timezone);
    ESP_LOGI(thisTag, "timezone_offset is:%s", weather_forecast->location.timezone_offset);

    for(uint8_t i = 0; i < weather_forecast->daily_count; i++)
    {
        ESP_LOGI(thisTag, "day %d code_day is:%d", i + 1, weather_forecast->daily->code_day);
        ESP_LOGI(thisTag, "day %d code_night is:%d", i + 1, weather_forecast->daily->code_night);
        ESP_LOGI(thisTag, "day %d date is:%s", i + 1, weather_forecast->daily->date);
        ESP_LOGI(thisTag, "day %d high is:%d", i + 1, weather_forecast->daily->high);
        ESP_LOGI(thisTag, "day %d humidity is:%d", i + 1, weather_forecast->daily->humidity);
        ESP_LOGI(thisTag, "day %d low is:%d", i + 1, weather_forecast->daily->low);
        ESP_LOGI(thisTag, "day %d precip is:%f", i + 1, weather_forecast->daily->precip);
        ESP_LOGI(thisTag, "day %d rainfall is:%f", i + 1, weather_forecast->daily->rainfall);
        ESP_LOGI(thisTag, "day %d text_day is:%s", i + 1, weather_forecast->daily->text_day);
        ESP_LOGI(thisTag, "day %d wind_direction is:%s", i + 1, weather_forecast->daily->wind_direction);
        ESP_LOGI(thisTag, "day %d wind_direction_degree is:%d", i, weather_forecast->daily->wind_direction_degree);
        ESP_LOGI(thisTag, "day %d wind_scale is:%d", i + 1, weather_forecast->daily->wind_scale);
        ESP_LOGI(thisTag, "day %d wind_speed is:%f", i + 1, weather_forecast->daily->wind_speed);
    }

    ESP_LOGI(thisTag, "last_update is:%s", weather_forecast->last_update);
}

static bool parse_Bili_json(const char *json_str, user_relation_response_t *response) 
{
    if (json_str == NULL || response == NULL) {
        ESP_LOGE(TAG, "Invalid parameters");
        return false;
    }

    // 初始化结构体
    memset(response, 0, sizeof(user_relation_response_t));
    
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            ESP_LOGE(TAG, "JSON parse error before: %s", error_ptr);
        }
        return false;
    }

    // 解析基本字段
    cJSON *code = cJSON_GetObjectItemCaseSensitive(root, "code");
    cJSON *message = cJSON_GetObjectItemCaseSensitive(root, "message");
    cJSON *ttl = cJSON_GetObjectItemCaseSensitive(root, "ttl");

    if (cJSON_IsNumber(code)) {
        response->code = code->valueint;
    }
    
    if (cJSON_IsString(message)) {
        response->message = message->valuestring; // 注意：这里指向JSON字符串的内存
    }
    
    if (cJSON_IsNumber(ttl)) {
        response->ttl = ttl->valueint;
    }

    // 解析data对象
    cJSON *data = cJSON_GetObjectItemCaseSensitive(root, "data");
    if (cJSON_IsObject(data)) {
        cJSON *mid = cJSON_GetObjectItemCaseSensitive(data, "mid");
        cJSON *following = cJSON_GetObjectItemCaseSensitive(data, "following");
        cJSON *whisper = cJSON_GetObjectItemCaseSensitive(data, "whisper");
        cJSON *black = cJSON_GetObjectItemCaseSensitive(data, "black");
        cJSON *follower = cJSON_GetObjectItemCaseSensitive(data, "follower");

        if (cJSON_IsNumber(mid)) response->data.mid = mid->valueint;
        if (cJSON_IsNumber(following)) response->data.following = following->valueint;
        if (cJSON_IsNumber(whisper)) response->data.whisper = whisper->valueint;
        if (cJSON_IsNumber(black)) response->data.black = black->valueint;
        if (cJSON_IsNumber(follower)) response->data.follower = follower->valueint;
    }

    cJSON_Delete(root);
    return true;
}

static void printBiliData(user_relation_response_t* user_relation_response)
{
    char* thisTag = "bilibili inf:";
    ESP_LOGI(thisTag, "bibi code is:%d", user_relation_response->code);
    ESP_LOGI(thisTag, "bibi message is:%s", user_relation_response->message);
    ESP_LOGI(thisTag, "bibi ttl is:%d", user_relation_response->ttl);

    ESP_LOGI(thisTag, "bibi black is:%d", user_relation_response->data.black);
    ESP_LOGI(thisTag, "bibi follower is:%d", user_relation_response->data.follower);
    ESP_LOGI(thisTag, "bibi following is:%d", user_relation_response->data.following);
    ESP_LOGI(thisTag, "bibi mid is:%d", user_relation_response->data.mid);
    ESP_LOGI(thisTag, "bibi whisper is:%d", user_relation_response->data.whisper);
}